#pragma once
#include<iostream>
#include<unistd.h>
#include"../comm/util.hpp"
#include "../comm/log.hpp"
#include<sys/wait.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
//只负责代码的编译
// 远端提交代码--> 编译服务  形成临时文件
//                              |
//                         1.编译通过 2.编译出错 需要形成临时文件,保存编译出错的结果
//                                          |
//                                     fork 父进程:继续执行
//                                          子进程:完成编译工作 --stderr 把显示到显示器的错误重定向
namespace ns_compiler
{
   //引入路径拼接功能
   using namespace ns_util;
   using namespace ns_log;
   class Compiler
   {
   public:
      Compiler()
      {}
      ~Compiler()
      {}

      //编译成功true 
      //输入参数:编译的文件名字没有后缀
      // temp 保存临时文件
      static bool Compile(const std::string &file_name)
      {
         pid_t pid=fork();
         if(pid<0)
         {
            LOG(ERROR)<<"内部错误,创建子进程失败"<<"\n";
            return false;
         }  
         else if(pid==0)
         {
            //创建一个文件来存储编译报错的信息
            umask(0); //把umask清0不然权限会有问题
            int _stderr =open(PathUtil::CompilerError(file_name).c_str(),O_CREAT|O_WRONLY,0644);
            if(_stderr <0)
            {
               LOG(WARNING) <<"没有成功形成stderr文件" <<"\n";
               exit(1);
            }

            //重定向标准错误到_stderr
            //g++编译报错会向显示器打印信息
            dup2(_stderr,2);

            //子进程--调用编译器完成对代码的编译工作
            //程序替换功能-不影响进程的文件描述符表
            // int execlp(const char *file, const char *arg, ...);
           execlp("g++","g++","-o",PathUtil::Exe(file_name).c_str(),
           PathUtil::Src(file_name).c_str(),"-std=c++11","-D","COMPILER_ONLINE",nullptr); //参数传完之后要以nullptr结尾
            LOG(ERROR)<<"启动编译器失败"<<"\n";
            exit(2);
         }
         else
         {
            //父进程
            waitpid(pid,nullptr,0);
            //编译是否成功 -- >形成可执行程序
            if(FileUtil::IsFileExists(PathUtil::Exe(file_name)))
            {
               LOG(INFO)<<PathUtil::Src(file_name)<<"编译成功"<<"\n";
               return true;
            }

         }
         LOG(ERROR)<<"编译失败,没有形成可执行程序"<<"\n";
         return false;
      }
   };
}
